﻿using SaveSation.Entity;
using SaveSation.Common;
using Common.UI;
using DefPack;
using DefPack.Common;
using DefPack.Entity;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows.Forms;
using static SaveSation.QuestionForm;

namespace SaveSation
{
    public partial class StartForm : Form
    {
        internal static AppSetting m_AppSetting = new AppSetting();
        internal static string m_ConfigFile = Path.Combine(Application.StartupPath, Application.ProductName + ".json");

        public static GroupEntity _actionGroup = new GroupEntity() { Index = 0, Name = "工具" };
        public static GroupEntity _lastGroup = new GroupEntity() { Index = 1, Name = "最近访问" };
        public static GroupEntity _defaultGroup = new GroupEntity() { Index = 2, Name = "默认分类" };
        public StartForm()
        {
            InitializeComponent();
            try
            {
                //初始化存档目录并加载默认配置
                AppSetting? appSetting;
                if (File.Exists(m_ConfigFile))
                {
                    appSetting = JsonSerializer.Deserialize<AppSetting>(AppSetting.ReadFile(m_ConfigFile), AppSetting.SerializerOptions);
                    if (appSetting == null)
                    {
                        throw new NullReferenceException(nameof(AppSetting));
                    }
                }
                else
                    appSetting = new AppSetting();
                m_AppSetting = appSetting;
                m_AppSetting.Groups.Sort();
                m_AppSetting.Items.Sort();
                if (!Directory.Exists(m_AppSetting.BackupPath))
                {
                    Directory.CreateDirectory(m_AppSetting.BackupPath);
                }
                initListView();
            }
            catch (Exception e1)
            {
                e1.Error();
                MessageBox.Show(this, e1.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        private void initListView()
        {
            try
            {
                listView1.Groups.Clear();
                listView1.Items.Clear();
                //初始化操作、最近访问、默认分类组
                _actionGroup.Index = listView1.Groups.Add(new ListViewGroup(_actionGroup.Name, HorizontalAlignment.Left));
                _lastGroup.Index = listView1.Groups.Add(new ListViewGroup(_lastGroup.Name, HorizontalAlignment.Left));
                _defaultGroup.Index = listView1.Groups.Add(new ListViewGroup(_defaultGroup.Name, HorizontalAlignment.Left));
                //初始化用户自定义分组
                foreach (var group in m_AppSetting.Groups)
                {
                    group.Index = listView1.Groups.Count;
                    listView1.Groups.Add(new ListViewGroup(group.Name, HorizontalAlignment.Left));
                }
                //if (m_AppSetting.Groups.Count > 0)
                //{
                //初始化操作组项目
                ListViewItem listViewItem = new ListViewItem($"添加配置");
                listViewItem.ImageIndex = 1;
                listViewItem.ToolTipText = "双击添加配置";
                listViewItem.Tag = "AddItem";
                listView1.Items.Add(listViewItem);
                listView1.Groups[_actionGroup.Index].Items.Add(listViewItem);

                listViewItem = new ListViewItem($"导入配置");
                listViewItem.ImageIndex = 1;
                listViewItem.ToolTipText = "双击导入配置";
                listViewItem.Tag = "ImportItem";
                listView1.Items.Add(listViewItem);
                listView1.Groups[_actionGroup.Index].Items.Add(listViewItem);

                listViewItem = new ListViewItem($"组管理");
                listViewItem.ImageIndex = 1;
                listViewItem.ToolTipText = "双击进入组管理";
                listViewItem.Tag = "GroupsManager";
                listView1.Items.Add(listViewItem);
                listView1.Groups[_actionGroup.Index].Items.Add(listViewItem);

                listViewItem = new ListViewItem($"更改备份\n目录");
                listViewItem.ImageIndex = 1;
                listViewItem.ToolTipText = "更改备份文件存储目录";
                listViewItem.Tag = "ChangeLocation";
                listView1.Items.Add(listViewItem);
                listView1.Groups[_actionGroup.Index].Items.Add(listViewItem);

                //}
                //初始化配置项目
                foreach (var item in m_AppSetting.Items)
                {
                    listViewItem = new ListViewItem(item.Name);
                    listViewItem.ImageIndex = GetIconID(item);
                    listViewItem.ToolTipText = "双击打开配置";
                    listViewItem.Tag = item;
                    listView1.Items.Add(listViewItem);
                    if (m_AppSetting.LastContent == item.UUID)
                    {
                        listView1.Groups[_lastGroup.Index].Items.Add(listViewItem);
                    }
                    else
                    {
                        int index = m_AppSetting.Groups.GetIndex(item);
                        listView1.Groups[index].Items.Add(listViewItem);
                    }
                }
                //保存程序配置到配置文件
                m_AppSetting.Save(m_ConfigFile);
            }
            catch (Exception e1)
            {
                e1.Error();
                MessageBox.Show(this, e1.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        /// <summary>
        /// 获取配置项图标ID
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        internal int GetIconID(ArchiveEntity entity)
        {
            try
            {
                string iconFile = Path.Combine(entity.FullPath, entity.Icon);
                if (File.Exists(iconFile))
                {
                    using (FileStream f = new FileStream(iconFile, FileMode.Open, FileAccess.Read))
                        imageList1.Images.Add(Image.FromStream(f));
                }
                else
                {
                    imageList1.Images.Add(ExtractIconFormExe(entity.Application));
                }
                return imageList1.Images.Count - 1;
            }
            catch (Exception e1)
            {
                e1.Error();
                return 0;
            }
        }
        /// <summary>
        /// 获取可执行文件默认图标
        /// </summary>
        /// <param name="exePath"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static Image ExtractIconFormExe(string exePath)
        {
            Icon? icon = Icon.ExtractAssociatedIcon(exePath);
            if (icon != null)
            {
                using (icon)
                {
                    using MemoryStream memory = new MemoryStream();
                    icon.Save(memory);
                    return Image.FromStream(memory);
                }
            }
            else
            {
                throw new Exception("No icon found in the executable.");
            }
        }

        private void listView1_DoubleClick(object sender, EventArgs e)
        {
            try
            {
                if (listView1.SelectedItems.Count == 0) return;
                ListViewItem item = listView1.SelectedItems[0];
                //判断点击项目附属对象的类型
                if (item.Tag is string)
                {
                    //如果点击的项目附属对象是文本，说明是操作按钮
                    string? actionName = item.Tag.ToString();
                    if (actionName == "AddItem")
                    {
                        //如果是添加配置按钮，显示添加配置窗口
                        ArchiveEntity? entity = null;
                        if (ItemForm.Show(ref entity, m_AppSetting.Groups, true) == DialogResult.OK)
                        {
                            if (entity == null) return;
                            ListViewItem listViewItem = new ListViewItem(entity.Name);
                            listViewItem.ImageIndex = GetIconID(entity);
                            listViewItem.ToolTipText = "双击打开配置";
                            listViewItem.Tag = entity;
                            listView1.Items.Add(listViewItem);
                            int index = m_AppSetting.Groups.GetIndex(entity);
                            if (index < listView1.Groups.Count) listView1.Groups[index].Items.Add(listViewItem);
                            m_AppSetting.Items.Add(entity);
                            Directory.CreateDirectory(Path.Combine(m_AppSetting.BackupPath, entity.UUID));
                            m_AppSetting.Save(m_ConfigFile);
                        }
                    }
                    else if (actionName == "ImportItem")
                    {
                        //如果是导入配置按钮，显示导入文件选择 窗口
                        openFileDialog1.Title = "请选择存档包";
                        openFileDialog1.Filter = "存档包（*.spack）|*.spack";
                        openFileDialog1.Multiselect = false;
                        openFileDialog1.FileName = "";
                        if (openFileDialog1.ShowDialog() != DialogResult.OK) return;
                        //打开存档对象，读取注释
                        using DefPackArchive archive = DefPackArchive.CreateWith(openFileDialog1.FileName);
                        if (archive.Note.IsNullOrEmpty())
                        {
                            throw new Exception("导入失败：文件或格式不支持！");
                        }
                        //实例化配置
                        ArchiveEntity? entity = JsonSerializer.Deserialize<ArchiveEntity>(archive.Note!, AppSetting.SerializerOptions);
                        if (entity == null)
                        {
                            throw new Exception("解析配置数据失败：文件或格式不支持！");
                        }
                        foreach (var it in m_AppSetting.Items)
                        {
                            if (it.UUID == entity.UUID)
                            {
                                //如果已经存在UUID一致的配置
                                var rt = MessageBox.Show(this, "已存在相同配置，是否导入配置并覆盖已存在的存档文件？\n\n是：导入配置并覆盖相同文件\n否：仅导入不存在的文件\n取消：取消导入", "操作成功", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
                                if (rt == DialogResult.Yes)
                                {
                                    using (ProcessForm p = new ProcessForm(archive))
                                    {
                                        //将存档包里的文件全部解压
                                        archive.DeCompressDirectory("", Path.GetDirectoryName(entity.FullPath));
                                    }
                                    it.Application = entity.Application;
                                    it.Tick = entity.Tick;
                                    it.SteamID = entity.SteamID;
                                    it.ArchivePath = entity.ArchivePath;
                                    it.BackupContent = entity.BackupContent;
                                    it.Icon = entity.Icon;
                                    it.MaxCount = entity.MaxCount;
                                    it.RestoreOperation = entity.RestoreOperation;
                                    it.TriggerEvent = entity.TriggerEvent;
                                    it.UnBuckup = entity.UnBuckup;
                                    it.UnDetect = entity.UnDetect;
                                    MessageBox.Show(this, "导入配置成功！", "操作成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
                                }
                                else if (rt == DialogResult.No)
                                {
                                    using (ProcessForm p = new ProcessForm(archive))
                                    {
                                        foreach (var file in archive.Entries)
                                        {
                                            if (file.IsDirectory) continue;
                                            if (File.Exists(Path.Combine(it.FullPath, file.Name)))
                                            {
                                                continue;
                                            }
                                            file.DeCompress(Path.Combine(it.FullPath, file.Name));
                                        }
                                    }
                                    MessageBox.Show(this, "导入配置成功！", "操作成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
                                }
                                return;
                            }
                        }
                        Directory.CreateDirectory(entity.FullPath);
                        using (ProcessForm p = new ProcessForm(archive))
                        {
                            archive.DeCompressDirectory("", Path.GetDirectoryName(entity.FullPath));
                        }
                        ListViewItem listViewItem = new ListViewItem(entity.Name);
                        listViewItem.ImageIndex = GetIconID(entity);
                        listViewItem.ToolTipText = "双击打开配置";
                        listViewItem.Tag = entity;
                        listView1.Items.Add(listViewItem);
                        int index = m_AppSetting.Groups.GetIndex(entity);
                        if (index < listView1.Groups.Count) listView1.Groups[index].Items.Add(listViewItem);
                        m_AppSetting.Items.Add(entity);
                        m_AppSetting.Save(m_ConfigFile);
                        MessageBox.Show(this, "导入配置成功！", "操作成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    else if (actionName == "GroupsManager")
                    {
                        var groups = m_AppSetting.Groups;
                        if (GroupsForm.Show(ref groups) == DialogResult.OK)
                        {
                            m_AppSetting.Groups.Sort();
                            m_AppSetting.Items.Sort();
                            initListView();
                            m_AppSetting.Save(m_ConfigFile);
                        }
                    }
                    else if (actionName == "ChangeLocation")
                    {
                        FolderBrowserDialog dialog = new FolderBrowserDialog();
                        dialog.Description = "请选择目标位置";
                        dialog.InitialDirectory = m_AppSetting.BackupPath;
                        dialog.ShowNewFolderButton = true;
                        if (dialog.ShowDialog() == DialogResult.OK)
                        {
                            string[] fileNames = Directory.EnumerateFileSystemEntries(m_AppSetting.BackupPath, "*.*", SearchOption.TopDirectoryOnly).ToArray();
                            using (ProcessForm p = new ProcessForm(out DefPack.Common.ProgressChangedEventHandler a, out ProgressCompletedEventHandler b, out ProgressExceptionEventHandler c))
                            {
                                int pi = 0;
                                for (int i = 0; i < fileNames.Length; i++)
                                {
                                    string dest = fileNames[i].Replace(m_AppSetting.BackupPath, dialog.SelectedPath);
                                    //File.Move(file, dest);
                                    //a.Invoke(null, new DefPack.Common.ProgressChangedEventArgs(0, null));
                                    Directory.Move(fileNames[i], dest);
                                    pi = (int)((double)(i + 1) / fileNames.Length * 100);
                                    a.Invoke(null, new DefPack.Common.ProgressChangedEventArgs(pi, pi, null));
                                }
                                b.Invoke(null, new ProgressCompletedEventArgs());
                            }
                            m_AppSetting.BackupPath = dialog.SelectedPath;
                            m_AppSetting.Save(m_ConfigFile);
                            MessageBox.Show(this, "更改文件夹位置成功！", "操作成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        }
                    }
                }
                else if (item.Tag is ArchiveEntity)
                {
                    //如果附属对象是配置项目实例
                    var archive = (ArchiveEntity)item.Tag;
                    if (archive == null) throw new Exception("未将对象引用设置到对象的实例");
                    if (!Directory.Exists(archive.ArchivePath.ExpandEnvironmentVariables()))
                    {
                        throw new DirectoryNotFoundException($"存档文件夹所在路径无效或不可用，请编辑配置文件重新确认所在位置！\n\n{archive.ArchivePath.ExpandEnvironmentVariables()}");
                    }
                    if (!Directory.Exists(archive.FullPath)) Directory.CreateDirectory(archive.FullPath);
                    m_AppSetting.LastContent = archive.UUID;
                    if (listView1.Groups.Count > 0)
                    {
                        if (listView1.Groups[_lastGroup.Index].Items.Count > 0)
                        {
                            var it = listView1.Groups[_lastGroup.Index].Items[0];
                            int id = m_AppSetting.Groups.GetIndex((ArchiveEntity)it.Tag);
                            listView1.Groups[id].Items.Add(it);
                            listView1.Groups[_lastGroup.Index].Items.Clear();
                        }
                        listView1.Groups[_lastGroup.Index].Items.Add(item);
                    }
                    this.Visible = false;
                    m_AppSetting.Save(m_ConfigFile);
                    new Form1(m_AppSetting, archive).ShowDialog();
                    archive.ArchiveItems = new List<ArchiveItem>();
                    this.Visible = true;
                }
            }
            catch (Exception e1)
            {
                e1.Error();
                MessageBox.Show(this, e1.Message, "操作失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void toolStripMenuItemEdit_Click(object sender, EventArgs e)
        {
            try
            {
                if (listView1.SelectedItems.Count == 0) return;
                ListViewItem item = listView1.SelectedItems[0];
                if (item.Tag is ArchiveEntity)
                {
                    ArchiveEntity? entity = (ArchiveEntity)item.Tag;
                    if (ItemForm.Show(ref entity, m_AppSetting.Groups) == DialogResult.OK)
                    {
                        if (entity == null) return;
                        item.Text = entity.Name;
                        item.ImageIndex = GetIconID(entity);
                        int id = m_AppSetting.Groups.GetIndex(entity);
                        listView1.Groups[id].Items.Add(item);
                        m_AppSetting.Save(m_ConfigFile);
                    }
                }
            }
            catch (Exception e1)
            {
                e1.Error();
                MessageBox.Show(this, e1.Message, "操作失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void toolStripMenuItemDelete_Click(object sender, EventArgs e)
        {
            try
            {
                if (listView1.SelectedItems.Count == 0) return;
                var item = listView1.SelectedItems[0];
                var archive = item.Tag as ArchiveEntity;
                var result = QuestionForm.Show($"您确认要删除配置[{item.Text}]吗?", "删除确认");
                if (result == QuestionResult.OK)
                {
                    listView1.Items.Remove(item);
                    if (archive != null) m_AppSetting.Items.Remove(archive);
                    m_AppSetting.Save(m_ConfigFile);
                    MessageBox.Show(this, "删除配置成功！", "操作成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else if (result == QuestionResult.DeleteStore)
                {
                    if (InputForm.Show(out string? name, $"删除操作不可撤销，请确认输入要删除的配置名称：\n{item.Text}", "确认删除") == DialogResult.OK)
                    {
                        if (!name.IsNullOrEmpty() && name == item.Text)
                        {
                            listView1.Items.Remove(item);
                            if (archive != null)
                            {
                                Directory.Delete(archive.FullPath, true);
                                m_AppSetting.Items.Remove(archive);
                                m_AppSetting.Save(m_ConfigFile);
                            }
                            MessageBox.Show(this, "删除配置成功！", "操作成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        }
                        else
                        {
                            throw new Exception("输入验证不正确！");
                        }
                    }
                }
            }
            catch (Exception e1)
            {
                e1.Error();
                MessageBox.Show(this, e1.Message, "操作失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
        {
            if (listView1.SelectedItems.Count == 0)
            {
                e.Cancel = true;
                return;
            }
            if (listView1.SelectedItems[0].Tag is string)
            {
                e.Cancel = true;
                return;
            }
            toolStripMenuItemMoveToGroup.DropDownItems.Clear();
            foreach (var item in m_AppSetting.Groups)
            {
                var it = new ToolStripMenuItem(item.Name);
                it.Tag = item.UUID;
                it.Click += new EventHandler((s, e) =>
                {
                    ToolStripMenuItem? st = s as ToolStripMenuItem;
                    if (st == null) return;
                    var archive = GetSelectArchive();
                    if (archive == null) return;
                    archive.GroupID = item.UUID;
                    m_AppSetting.Save(m_ConfigFile);
                    int index = m_AppSetting.Groups.GetIndex(archive);
                    listView1.Groups[index].Items.Add(listView1.SelectedItems[0]);
                });
                toolStripMenuItemMoveToGroup.DropDownItems.Add(it);
            }
        }

        private void toolStripMenuItemRunApplication_Click(object sender, EventArgs e)
        {
            try
            {
                var item = GetSelectArchive();
                if (item == null) throw new Exception("未将对象引用设置到对象的实例");
                if (!File.Exists(item.Application) && item.SteamID.IsNullOrEmpty())
                {
                    throw new Exception("请选择应用程序位置或填写StreamID！");
                }
                if (!item.SteamID.IsNullOrEmpty())
                {
                    Process process = new Process();
                    ProcessStartInfo processStartInfo = new ProcessStartInfo($"Steam://run/{item.SteamID}/");
                    process.StartInfo = processStartInfo;
                    process.StartInfo.UseShellExecute = true;
                    process.Start();
                }
                else if (File.Exists(item.Application))
                {
                    Process process = new Process();
                    ProcessStartInfo processStartInfo = new ProcessStartInfo(item.Application);
                    process.StartInfo = processStartInfo;
                    process.StartInfo.UseShellExecute = true;
                    process.Start();
                }
            }
            catch (Exception e1)
            {
                e1.Error();
                MessageBox.Show(this, e1.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void toolStripMenuItemAbout_Click(object sender, EventArgs e)
        {
            new AboutForm().ShowDialog();
        }

        private void toolStripMenuItemExport_Click(object sender, EventArgs e)
        {
            try
            {
                var item = GetSelectArchive();
                if (item == null) throw new Exception("未将对象引用设置到对象的实例");
                saveFileDialog1.Title = "导出";
                saveFileDialog1.Filter = "存档包（*.spack）|*.spack";
                saveFileDialog1.FileName = item.Name + ".spack";
                saveFileDialog1.DefaultExt = "spack";
                saveFileDialog1.InitialDirectory = Application.StartupPath;
                if (saveFileDialog1.ShowDialog() != DialogResult.OK) return;
                DefPackArchive.CreateArchive(saveFileDialog1.FileName, item.ToString());
                using DefPackArchive archive = DefPackArchive.CreateWith(saveFileDialog1.FileName);
                using (ProcessForm p = new ProcessForm(archive))
                {
                    archive.CompressDirectory(item.FullPath);
                    archive.Close();
                }
                MessageBox.Show(this, "导出存档包成功！", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception e1)
            {
                e1.Error();
                MessageBox.Show(this, e1.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void toolStripMenuItemOpenStore_Click(object sender, EventArgs e)
        {
            try
            {
                var item = GetSelectArchive();
                if (item != null && !item.ArchivePath.IsNullOrEmpty() && Directory.Exists(item.ArchivePath.ExpandEnvironmentVariables()))
                {
                    Process process = new Process();
                    ProcessStartInfo processStartInfo = new ProcessStartInfo($"{item.ArchivePath.ExpandEnvironmentVariables()}");
                    process.StartInfo = processStartInfo;
                    process.StartInfo.UseShellExecute = true;
                    process.Start();
                }
                else
                {
                    throw new DirectoryNotFoundException("存档位置为空或不可用！\n\n" + item.ArchivePath.ExpandEnvironmentVariables());
                }
            }
            catch (Exception e1)
            {
                e1.Error();
                MessageBox.Show(this, e1.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void toolStripMenuItemOpenBackupStore_Click(object sender, EventArgs e)
        {
            try
            {
                var item = GetSelectArchive();
                if (item != null && !item.FullPath.IsNullOrEmpty() && Directory.Exists(item.FullPath))
                {
                    Process process = new Process();
                    ProcessStartInfo processStartInfo = new ProcessStartInfo($"{item.FullPath}");
                    process.StartInfo = processStartInfo;
                    process.StartInfo.UseShellExecute = true;
                    process.Start();
                }
                else
                {
                    throw new DirectoryNotFoundException("目录位置为空或不可用！\n\n" + item?.FullPath);
                }
            }
            catch (Exception e1)
            {
                e1.Error();
                MessageBox.Show(this, e1.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        private ArchiveEntity? GetSelectArchive()
        {
            if (listView1.SelectedItems.Count == 0) return null;
            ListViewItem item = listView1.SelectedItems[0];
            if (item.Tag is ArchiveEntity)
            {
                return (ArchiveEntity)item.Tag;
            }
            else
            {
                return null;
            }
        }
    }

}
